package com.bxj.mybatis.generator.plugin;

import org.mybatis.generator.api.CommentGenerator;
import org.mybatis.generator.api.GeneratedJavaFile;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.PluginAdapter;
import org.mybatis.generator.api.dom.java.*;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;

public class DubboServicePlugin extends PluginAdapter {


    private String dubboServiceProject;
    private String dubboServiceImplPackage;
    private String dubboServicePackage;
    private String dtoPackage;
    private String servicePackage;
    private String dto = "";
    private String modelPackage;

    public boolean validate(List<String> warnings) {
        dubboServiceProject = properties.getProperty("dubboServiceProject");
        if (StringUtils.isEmpty(dubboServiceProject))
            return false;
        dubboServiceImplPackage = properties.getProperty("dubboServiceImplPackage");
        if (StringUtils.isEmpty(dubboServiceImplPackage))
            return false;
        dubboServicePackage = properties.getProperty("dubboServicePackage");
        if (StringUtils.isEmpty(dubboServicePackage))
            return false;
        servicePackage = properties.getProperty("servicePackage");
        if (StringUtils.isEmpty(servicePackage))
            return false;
        dtoPackage = properties.getProperty("dtoPackage");
        if (StringUtils.isEmpty(dtoPackage))
            return false;
        String contextEnableDto = context.getProperty("enableDto");
        String enableDto = properties.getProperty("enableDto");
        if ("true".equals(enableDto) || "true".equals(contextEnableDto))
            dto = "";

        modelPackage = properties.getProperty("modelPackage");
        if (StringUtils.isEmpty(modelPackage)) {
            return false;
        }
        return true;
    }


    @Override
    public List<GeneratedJavaFile> contextGenerateAdditionalJavaFiles(IntrospectedTable introspectedTable) {
        List<GeneratedJavaFile> answer = new ArrayList<GeneratedJavaFile>();
        boolean dubboServiceGenerator = MybatisUtils.getTableProperties(introspectedTable, "dubboServiceGenerator", true);

        if (!dubboServiceGenerator)
            return answer;

        String shortName = introspectedTable.getFullyQualifiedTable().getDomainObjectName();
        String paramName = shortName.substring(0, 1).toLowerCase() + shortName.substring(1);
        String serviceInterfaceName = dubboServicePackage + ".I" + shortName + "DubboService";


        CommentGenerator commentGenerator = context.getCommentGenerator();
        String serviceImplName = dubboServiceImplPackage + "." + shortName + "DubboServiceImpl";


        if (!MybatisUtils.checkReplaceIfExists(introspectedTable, dubboServiceProject, dubboServiceImplPackage, shortName + "DubboServiceImpl.java"))
            return new ArrayList<GeneratedJavaFile>();

        FullyQualifiedJavaType type = new FullyQualifiedJavaType(
                serviceImplName);
        TopLevelClass topLevelClass = new TopLevelClass(type);
        MybatisUtils.addJavaDocLines(topLevelClass);
        topLevelClass.addAnnotation("@Component(\"" + paramName + "DubboService\")");
        topLevelClass.setVisibility(JavaVisibility.PUBLIC);
        topLevelClass.addSuperInterface(new FullyQualifiedJavaType(serviceInterfaceName));
        if (dto.isEmpty()) {
            topLevelClass.addImportedType(new FullyQualifiedJavaType(modelPackage + "." + shortName));
        } else {
            topLevelClass.addImportedType(introspectedTable.getBaseRecordType());
        }
        topLevelClass.addImportedType(servicePackage + "." + shortName + "Service");
        topLevelClass.addImportedType(new FullyQualifiedJavaType(serviceInterfaceName));
        topLevelClass.addImportedType(new FullyQualifiedJavaType("org.springframework.stereotype.Component"));
        topLevelClass.addImportedType(new FullyQualifiedJavaType("javax.annotation.Resource"));
//        topLevelClass.addImportedType(new FullyQualifiedJavaType("com.ifeng.matrix.BeanMapperUtils"));
        if (!dto.isEmpty()) {
            topLevelClass.addImportedType(new FullyQualifiedJavaType("com.ifeng.matrix.common.dto.PageResultDto"));
            topLevelClass.addImportedType(new FullyQualifiedJavaType(dtoPackage + "." + shortName + ""));
        }
        topLevelClass.addImportedType(new FullyQualifiedJavaType("java.util.List"));

//        topLevelClass.addImportedType(new FullyQualifiedJavaType(mapperPackage + ".master." + shortName + "MasterMapper"));
//        topLevelClass.addImportedType(new FullyQualifiedJavaType(mapperPackage + ".slave." + shortName + "SlaveMapper"));

        //@Resource
        //***Service ***Service;
        Field service = new Field(paramName + "Service", new FullyQualifiedJavaType(shortName + "Service"));
        service.addAnnotation("@Resource");
        topLevelClass.addField(service);
        //@Resource
        //***Service ***Service;
//        Field beanMapperUtils = new Field("beanMapperUtils", new FullyQualifiedJavaType("BeanMapperUtils"));
//        beanMapperUtils.addAnnotation("@Resource");
//        topLevelClass.addField(beanMapperUtils);

        commentGenerator.addJavaFileComment(topLevelClass);
        addSelectById(answer, topLevelClass, introspectedTable);
        addSelectSelective(answer, topLevelClass, introspectedTable);
        addSelectPage(answer, topLevelClass, introspectedTable);
        addInsert(answer, topLevelClass, introspectedTable);
//        addDeleteByPrimaryKey(answer, topLevelClass, introspectedTable);
        addUpdateByPrimaryKeySelective(answer, topLevelClass, introspectedTable);


        return answer;
    }

    private void addSelectById(List<GeneratedJavaFile> answer, TopLevelClass levelClass, IntrospectedTable introspectedTable) {
        String shortName = introspectedTable.getFullyQualifiedTable().getDomainObjectName();
        String paramName = shortName.substring(0, 1).toLowerCase() + shortName.substring(1);

        Method method1 = new Method();
        method1.setVisibility(JavaVisibility.PUBLIC);
        method1.setName(MybatisUtils.getTableProperties(introspectedTable, "selectByPrimaryKeyStatementId", "selectById"));
        if (introspectedTable.getPrimaryKeyColumns().size() > 0)
            method1.addParameter(new Parameter(introspectedTable.getPrimaryKeyColumns().get(0).getFullyQualifiedJavaType(), "id", false));


        method1.setReturnType(new FullyQualifiedJavaType(shortName));
        //ChatApp chatApp = beanMapperUtils.map(object, ChatApp.class);
        //chatUserService.selectSelective(object)
        if (dto.isEmpty()) {
            method1.addBodyLine("return " + paramName + "Service." + MybatisUtils.getTableProperties(introspectedTable, "selectByPrimaryKeyStatementId", "selectById") + "(id);");
        } else {
            method1.addBodyLine(shortName + " " + paramName + " = beanMapperUtils.map(" + paramName + "" + ", " + shortName + ".class);");
            method1.addBodyLine("return beanMapperUtils.map(" + paramName + "Service." + MybatisUtils.getTableProperties(introspectedTable, "selectByPrimaryKeyStatementId", "selectById") + "(id), " + shortName + ".class);");
        }
        levelClass.addMethod(method1);

        answer.add(new GeneratedJavaFile(levelClass, dubboServiceProject, context.getJavaFormatter()));

    }


    //    private GeneratedJavaFile addSelectSelectiveMethod(TopLevelClass levelClass, IntrospectedTable introspectedTable) {
//        Method method = new Method();
//        method.setVisibility(JavaVisibility.PUBLIC);
//        String shortName = introspectedTable.getFullyQualifiedTable().getDomainObjectName();
//        String paramName = shortName.substring(0, 1).toLowerCase() + shortName.substring(1);
//        method.setName("selectSelective");
//        method.addParameter(new Parameter(new FullyQualifiedJavaType(shortName), paramName, false));
//        levelClass.addImportedType(new FullyQualifiedJavaType(servicePackage + "." + shortName));
//        levelClass.addImportedType(new FullyQualifiedJavaType("java.util.List"));
//        levelClass.addImportedType(new FullyQualifiedJavaType("com.ifeng.common.pojo." + shortName));
//        method.setReturnType(new FullyQualifiedJavaType("List<" + shortName + ">"));
//        method.addBodyLine("return null;");
//        levelClass.addMethod(method);
//
//        return new GeneratedJavaFile(levelClass, serviceProject, context.getJavaFormatter());
//    }
    private void addSelectSelective(List<GeneratedJavaFile> answer, TopLevelClass levelClass, IntrospectedTable introspectedTable) {
        String shortName = introspectedTable.getFullyQualifiedTable().getDomainObjectName();
        String paramName = shortName.substring(0, 1).toLowerCase() + shortName.substring(1);

        Method method1 = new Method();
        method1.setVisibility(JavaVisibility.PUBLIC);
        method1.setName(MybatisUtils.getTableProperties(introspectedTable, "selectSelectiveStatementId", "selectSelective"));
        method1.addParameter(new Parameter(new FullyQualifiedJavaType(shortName + ""), paramName + "", false));

        method1.setReturnType(new FullyQualifiedJavaType("List<" + shortName + "" + ">"));
        //ChatApp chatApp = beanMapperUtils.map(object, ChatApp.class);
        //chatUserService.selectSelective(object)
        if (dto.isEmpty()) {
            method1.addBodyLine("return " + paramName + "Service." + MybatisUtils.getTableProperties(introspectedTable, "selectSelectiveStatementId", "selectSelective") + "(" + paramName + ");");
        } else {
            method1.addBodyLine(shortName + " " + paramName + " = beanMapperUtils.map(" + paramName + "" + ", " + shortName + ".class);");
            method1.addBodyLine("return beanMapperUtils.map(" + paramName + "Service." + MybatisUtils.getTableProperties(introspectedTable, "selectSelectiveStatementId", "selectSelective") + "(" + paramName + "), " + shortName + ".class);");
        }
        levelClass.addMethod(method1);

        answer.add(new GeneratedJavaFile(levelClass, dubboServiceProject, context.getJavaFormatter()));

    }

    private void addSelectPage(List<GeneratedJavaFile> answer, TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
        String shortName = introspectedTable.getFullyQualifiedTable().getDomainObjectName();
        String paramName = shortName.substring(0, 1).toLowerCase() + shortName.substring(1);


        Method method1 = new Method();
        method1.setVisibility(JavaVisibility.PUBLIC);
        method1.setName(MybatisUtils.getTableProperties(introspectedTable, "selectPageStatementId", "selectPage"));
        method1.addParameter(new Parameter(new FullyQualifiedJavaType(shortName + ""), paramName + "", false));
        topLevelClass.addImportedType(new FullyQualifiedJavaType("com.ifeng.matrix.common.domain.PageResult"));
//        ChatApp chatApp = beanMapperUtils.map(object, ChatApp.class);
//        return beanMapperUtils.map(chatUserService.selectPage(chatUser), ChatUserDto.class);
        method1.setReturnType(new FullyQualifiedJavaType("PageResult" + dto + "<" + shortName + "" + ">"));

        if (dto.isEmpty()) {
            method1.addBodyLine("return " + paramName + "Service." + MybatisUtils.getTableProperties(introspectedTable, "selectPageStatementId", "selectPage") + "(" + paramName + ");");
        } else {
            method1.addBodyLine(shortName + " " + paramName + " = beanMapperUtils.map(" + paramName + "" + ", " + shortName + ".class);");
            method1.addBodyLine("return beanMapperUtils.map(" + paramName + "Service." + MybatisUtils.getTableProperties(introspectedTable, "selectPageStatementId", "selectPage") + "(" + paramName + "), " + shortName + ".class);");
        }

        topLevelClass.addMethod(method1);

        answer.add(new GeneratedJavaFile(topLevelClass, dubboServiceProject, context.getJavaFormatter()));

    }

    private void addInsert(List<GeneratedJavaFile> answer, TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
        String shortName = introspectedTable.getFullyQualifiedTable().getDomainObjectName();
        String paramName = shortName.substring(0, 1).toLowerCase() + shortName.substring(1);


        Method method1 = new Method();
        method1.setVisibility(JavaVisibility.PUBLIC);
        method1.setName(MybatisUtils.getTableProperties(introspectedTable, "insertStatementId", "insert"));
        method1.addParameter(new Parameter(new FullyQualifiedJavaType(shortName + ""), paramName + "", false));
        method1.setReturnType(FullyQualifiedJavaType.getIntInstance());
//        ChatUser chatUser = beanMapperUtils.map(chatUserDto, ChatUser.class);
//        int ret = chatUserService.insert(chatUser);
//        beanMapperUtils.map(chatUser, chatUserDto);
//        return ret;
        if (dto.isEmpty()) {
            method1.addBodyLine("int ret = " + paramName + "Service.insert(" + paramName + ");");
        } else {
            method1.addBodyLine(shortName + " " + paramName + " = beanMapperUtils.map(" + paramName + "" + ", " + shortName + ".class);");
            method1.addBodyLine("int ret = " + paramName + "Service.insert(" + paramName + ");");
            if (dto.isEmpty()) {
                method1.addBodyLine("beanMapperUtils.map(" + paramName + ", " + paramName + ");");
            }
        }
        method1.addBodyLine("return ret;");
        topLevelClass.addMethod(method1);

        answer.add(new GeneratedJavaFile(topLevelClass, dubboServiceProject, context.getJavaFormatter()));
    }

    private void addDeleteByPrimaryKey(List<GeneratedJavaFile> answer, TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
        String shortName = introspectedTable.getFullyQualifiedTable().getDomainObjectName();
        String paramName = shortName.substring(0, 1).toLowerCase() + shortName.substring(1);


        Method method1 = new Method();
        method1.setVisibility(JavaVisibility.PUBLIC);
        method1.setName(MybatisUtils.getTableProperties(introspectedTable, "deleteByPrimaryKeyStatementId", "deleteById"));
        if (introspectedTable.getPrimaryKeyColumns().size() > 0)
            method1.addParameter(new Parameter(introspectedTable.getPrimaryKeyColumns().get(0).getFullyQualifiedJavaType(), "id", false));
        method1.setReturnType(FullyQualifiedJavaType.getIntInstance());
        method1.addBodyLine("return " + paramName + "Service." + MybatisUtils.getTableProperties(introspectedTable, "deleteByPrimaryKeyStatementId", "deleteById") + "(id);");
        topLevelClass.addMethod(method1);

        answer.add(new GeneratedJavaFile(topLevelClass, dubboServiceProject, context.getJavaFormatter()));
    }

    private void addUpdateByPrimaryKeySelective(List<GeneratedJavaFile> answer, TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
        String shortName = introspectedTable.getFullyQualifiedTable().getDomainObjectName();
        String paramName = shortName.substring(0, 1).toLowerCase() + shortName.substring(1);


        Method method1 = new Method();
        method1.setVisibility(JavaVisibility.PUBLIC);
        method1.setName(MybatisUtils.getTableProperties(introspectedTable, "updateByPrimaryKeySelectiveStatementId", "updateSelectiveById"));
        method1.addParameter(new Parameter(new FullyQualifiedJavaType(shortName + ""), paramName + "", false));
        method1.setReturnType(FullyQualifiedJavaType.getIntInstance());
        if (dto.isEmpty()) {
            method1.addBodyLine("return " + paramName + "Service." + MybatisUtils.getTableProperties(introspectedTable, "updateByPrimaryKeySelectiveStatementId", "updateSelectiveById") + "(" + paramName + ");");
        } else {
            method1.addBodyLine(shortName + " " + paramName + " = beanMapperUtils.map(" + paramName + "" + ", " + shortName + ".class);");
            method1.addBodyLine("return " + paramName + "Service." + MybatisUtils.getTableProperties(introspectedTable, "updateByPrimaryKeySelectiveStatementId", "updateSelectiveById") + "(" + paramName + ");");
        }
        topLevelClass.addMethod(method1);


        answer.add(new GeneratedJavaFile(topLevelClass, dubboServiceProject, context.getJavaFormatter()));
    }


}
